home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / exidy.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  9KB  |  306 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ***************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "vidhrdw/generic.h"
  11.  
  12. unsigned char *exidy_characterram;
  13. unsigned char *exidy_color_latch;
  14. unsigned char *exidy_sprite_no;
  15. unsigned char *exidy_sprite_enable;
  16. unsigned char *exidy_sprite1_xpos;
  17. unsigned char *exidy_sprite1_ypos;
  18. unsigned char *exidy_sprite2_xpos;
  19. unsigned char *exidy_sprite2_ypos;
  20.  
  21. int exidy_collision;
  22. int exidy_collision_counter;
  23.  
  24. static struct osd_bitmap *motion_object_1_vid;
  25. static struct osd_bitmap *motion_object_2_vid;
  26.  
  27. static unsigned char exidy_dirtycharacter[256];
  28.  
  29. #define COLOR_BLUE 0
  30. #define COLOR_GREEN 1
  31. #define COLOR_RED 2
  32.  
  33. /***************************************************************************
  34. exidy_vh_start
  35. ***************************************************************************/
  36.  
  37. int exidy_vh_start(void)
  38. {
  39.     exidy_collision_counter = 0;
  40.  
  41.     if (generic_vh_start()!=0)
  42.         return 1;
  43.  
  44.     if ((motion_object_1_vid = osd_create_bitmap(16,16)) == 0)
  45.     {
  46.         generic_vh_stop();
  47.         return 1;
  48.     }
  49.  
  50.     if ((motion_object_2_vid = osd_create_bitmap(16,16)) == 0)
  51.     {
  52.         osd_free_bitmap(motion_object_1_vid);
  53.         generic_vh_stop();
  54.         return 1;
  55.     }
  56.  
  57.     return 0;
  58. }
  59.  
  60. /***************************************************************************
  61. exidy_vh_stop
  62. ***************************************************************************/
  63.  
  64. void exidy_vh_stop(void)
  65. {
  66.     osd_free_bitmap(motion_object_1_vid);
  67.     osd_free_bitmap(motion_object_2_vid);
  68.     generic_vh_stop();
  69. }
  70.  
  71. /***************************************************************************
  72. exidy_characterram_w
  73. ***************************************************************************/
  74.  
  75. WRITE_HANDLER( exidy_characterram_w )
  76. {
  77.     if (exidy_characterram[offset] != data)
  78.     {
  79.         exidy_dirtycharacter[offset / 8 % 256] = 1;
  80.  
  81.         exidy_characterram[offset] = data;
  82.     }
  83. }
  84.  
  85. /***************************************************************************
  86. exidy_color_w
  87. ***************************************************************************/
  88.  
  89. WRITE_HANDLER( exidy_color_w )
  90. {
  91.     int i;
  92.  
  93.     exidy_color_latch[offset]=data;
  94.  
  95.     for (i=0;i<8;i++)
  96.     {
  97.         int r,g,b;
  98.  
  99.         r=((exidy_color_latch[COLOR_RED]>>i) & 0x01) * 0xFF;
  100.         g=((exidy_color_latch[COLOR_GREEN]>>i) & 0x01) * 0xFF;
  101.         b=((exidy_color_latch[COLOR_BLUE]>>i) & 0x01) * 0xFF;
  102.  
  103.         palette_change_color(i,r,g,b);
  104.     }
  105. }
  106.  
  107. /***************************************************************************
  108. exidy_check_collision
  109.  
  110. It might seem strange to put the collision-checking routine in vidhrdw.
  111. However, Exidy hardware checks for two types of collisions based on the
  112. video signals.  If the Motion Object 1 and Motion Object 2 signals are
  113. on at the same time, an M1M2 collision bit gets set.  If the Motion Object 1
  114. and Background Character signals are on at the same time, an M1CHAR
  115. collision bit gets set.  So effectively, there's a pixel-by-pixel collision
  116. check comparing Motion Object 1 (the player) to the background and to the
  117. other Motion Object (typically a bad guy).
  118.  
  119. Now, where things get a little weird is in how these bits get checked.
  120. These bits can cause IRQs, depending on whether or not certain traces on
  121. the board are cut.  Targ, Spectar, and Pepper II don't even check these
  122. collision bits.  Venture generates an IRQ for each collision but only
  123. checks the VBLANK bit.  MouseTrap should generate an IRQ for each
  124. collision, but the game works just by setting the two collision bits
  125. once per frame.
  126.  
  127. We can't just check the color of the main bitmap at a given location, because one
  128. of our video signals might have overdrawn another one.  So here's what we do:
  129. 1)  Redraw the background, Motion Object 1, and Motion Object 2 into separate
  130. bitmaps, but clip to where Motion Object 2 is located.
  131. 2)  Scan through the bitmaps and look for bits that are on at the same time.
  132. 3)  Save the number of scanlines causing collisions for Venture.
  133. ***************************************************************************/
  134.  
  135. void exidy_check_collision(struct osd_bitmap *bitmap)
  136. {
  137.     int sx,sy,org_x,org_y;
  138.     struct rectangle clip;
  139.     unsigned char enable_set=0;
  140.     int collision;
  141.  
  142.     /* reset collision flags */
  143.     exidy_collision &= 0xEB;
  144.  
  145.     clip.min_x=0;
  146.     clip.max_x=15;
  147.     clip.min_y=0;
  148.     clip.max_y=15;
  149.  
  150.     org_x = 236-*exidy_sprite1_xpos-4;
  151.     org_y = 244-*exidy_sprite1_ypos-4;
  152.     if ((*exidy_sprite_enable&0x20)==0x20)
  153.         enable_set=1;
  154.  
  155.     fillbitmap(motion_object_1_vid,Machine->pens[0],&clip);
  156.     fillbitmap(motion_object_2_vid,Machine->pens[0],&clip);
  157.  
  158.     /* Draw Motion Object 1 */
  159.     drawgfx(motion_object_1_vid,Machine->gfx[1],
  160.         (*exidy_sprite_no & 0x0F)+16*enable_set,0,
  161.         0,0,0,0,&clip,TRANSPARENCY_NONE,0);
  162.  
  163.     /* Draw Motion Object 2 clipped to Motion Object 1's location */
  164.     if (!(*exidy_sprite_enable&0x40))
  165.     {
  166.         sx = (236-*exidy_sprite2_xpos-4)-org_x;
  167.         sy = (244-*exidy_sprite2_ypos-4)-org_y;
  168.  
  169.         drawgfx(motion_object_2_vid,Machine->gfx[1],
  170.             ((*exidy_sprite_no>>4) & 0x0F)+32,1,
  171.             0,0,sx,sy,&clip,TRANSPARENCY_NONE,0);
  172.     }
  173.  
  174.     /* Now check for Collision */
  175.     for (sy=0;sy<16;sy++)
  176.     {
  177.         for (sx=0;sx<16;sx++)
  178.         {
  179.             if (read_pixel(motion_object_1_vid, sx, sy) != Machine->pens[0])
  180.             {
  181.                 collision=0;
  182.  
  183.                 /* Check for background collision (M1CHAR) */
  184.                 if (read_pixel(bitmap, org_x+sx, org_y+sy) != Machine->pens[0])
  185.                 {
  186.                     exidy_collision|=0x04;
  187.                     collision=1;
  188.                 }
  189.  
  190.                 /* Check for Motion Object collision (M1M2) */
  191.                 if (read_pixel(motion_object_2_vid, sx, sy) != Machine->pens[0])
  192.                 {
  193.                     exidy_collision|=0x10;
  194.                     collision=1;
  195.                 }
  196.  
  197.                 exidy_collision_counter+=collision;
  198.             }
  199.         }
  200.     }
  201. }
  202.  
  203.  
  204.  
  205. /***************************************************************************
  206.  
  207.   Draw the game screen in the given osd_bitmap.
  208.   Do NOT call osd_update_display() from this function, it will be called by
  209.   the main emulation engine.
  210.  
  211. ***************************************************************************/
  212. void exidy_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  213. {
  214.     int offs,i;
  215.  
  216.  
  217.     if (palette_recalc())
  218.         memset(dirtybuffer,1,videoram_size);
  219.  
  220.     /* for every character in the Video RAM, check if it has been modified */
  221.     /* since last time and update it accordingly. */
  222.     for (offs = videoram_size - 1;offs >= 0;offs--)
  223.     {
  224.         int charcode;
  225.  
  226.  
  227.         charcode = videoram[offs];
  228.  
  229.         if (dirtybuffer[offs] || exidy_dirtycharacter[charcode])
  230.         {
  231.             int sx,sy,color;
  232.  
  233.  
  234.         /* decode modified characters */
  235.             if (exidy_dirtycharacter[charcode] == 1)
  236.             {
  237.                 decodechar(Machine->gfx[0],charcode,exidy_characterram,
  238.                         Machine->drv->gfxdecodeinfo[0].gfxlayout);
  239.                 exidy_dirtycharacter[charcode] = 2;
  240.             }
  241.  
  242.  
  243.             dirtybuffer[offs] = 0;
  244.  
  245.             sx = 8 * (offs % 32);
  246.             sy = 8 * (offs / 32);
  247.             color = (charcode & 0xC0) >> 6;
  248.             drawgfx(tmpbitmap,Machine->gfx[0],
  249.                     charcode,color,
  250.                     0,0,sx,sy,
  251.                     &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  252.         }
  253.     }
  254.  
  255.  
  256.     for (i = 0;i < 256;i++)
  257.     {
  258.         if (exidy_dirtycharacter[i] == 2)
  259.             exidy_dirtycharacter[i] = 0;
  260.     }
  261.  
  262.     /* copy the character mapped graphics */
  263.     copybitmap(bitmap,tmpbitmap,0,0,0,0,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  264.  
  265.     exidy_check_collision(bitmap);
  266.  
  267.     /* Draw the sprites */
  268.     {
  269.         int sx,sy;
  270.         unsigned char enable_set = 0;
  271.  
  272.         /* Draw Motion Object 2 first. */
  273.         if (!(*exidy_sprite_enable&0x40))
  274.         {
  275.             sx = 236-*exidy_sprite2_xpos-4;
  276.             sy = 244-*exidy_sprite2_ypos-4;
  277.  
  278.             drawgfx(bitmap,Machine->gfx[1],
  279.                 ((*exidy_sprite_no>>4) & 0x0F)+32,1,
  280.                 0,0,
  281.                 sx,sy,
  282.                 &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  283.         }
  284.  
  285.         /* Now draw Motion Object 1. */
  286.         if (!(*exidy_sprite_enable&0x80) || *exidy_sprite_enable&0x10)
  287.         {
  288.             sx = 236-*exidy_sprite1_xpos-4;
  289.             sy = 244-*exidy_sprite1_ypos-4;
  290.  
  291.             if (sy < 0) sy = 0;
  292.  
  293.             if ((*exidy_sprite_enable&0x20)==0x20)
  294.                 enable_set=1;
  295.  
  296.             drawgfx(bitmap,Machine->gfx[1],
  297.                 (*exidy_sprite_no & 0x0F)+16*enable_set,0,
  298.                 0,0,
  299.                 sx,sy,
  300.                 &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  301.         }
  302.  
  303.     }
  304. }
  305.  
  306.